<template>
  <div>
    <search ref="search" :search="search" @handleSearch="handleSearch" @handleReset="handleReset" />

    <div class="app-container" style="margin: 3px 15px;">
      <el-alert v-if="tips" :title="tips.content" :type="tips.type" style="margin-bottom: 5px;" />
      <div class="filter-container">
        <!-- 表头的 actions -->
        <component :is="'el-' + item.el" v-for="item in actions" :key="item.name" v-action="item.permission"
          :class="item.class" :icon="item.icon" :type="item.type === undefined ? 'primary' : item.type"
          style="margin-bottom: 5px;" @click="actionClick(item)">
          {{ item.label }}
        </component>
        <el-button v-if="selectedIds.length > 0 && hidePagination" type="danger" size="small"
          @click="handleDelete(selectedIds)">批量删除</el-button>

        <div class="fr">
          <el-button icon="el-icon-refresh" class="mr-2" size="mini" @click="refreshPage" />
          <el-dropdown :hide-on-click="false">
            <span class="el-dropdown-link">
              <el-button icon="el-icon-menu" size="mini" />
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item v-for="(item, k) in headers" v-if="item.label.length > 0" :key="item.prop">
                <el-checkbox v-model="item.show" /> {{ item.label }}
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
      </div>

      <el-table :key="updateKey" v-loading="loading" :data="source" style="width: 100%" v-bind="$attrs"
        v-on="getTableEvents">
        <el-table-column v-for="(item, k) in getHeaders" v-if="item.type !== 'selection'" :key="item.prop"
          v-bind="getAttrsValue(item)">
          <template v-slot="scope">
            <div v-if="isActionOrComponent(getValue(scope, item))">
              <component :is="renderTypeList[getMatchRenderFunction(item)].target"     :cell-list="getValue(scope, item)"
                :row="scope.row" :parent="getParent" :catch-table="getTableObject()" @click.native="($event) => {
                  handleNativeClick(getAttrsValue(item), $event)
                }" />
            </div>
            <span v-else>
              {{ getValue(scope, item) }}
            </span>
          </template>

        </el-table-column>
        <el-table-column v-else type="selection" width="50px" :selectable="selectable" />
      </el-table>

      <el-row v-if="!hidePagination" justify="end" type="flex">
        <el-col :span="8" style="padding-top: 14px">
          <el-button v-if="this.selectedIds.length > 0" icon="el-icon-delete" style="float: left" type="danger"
            size="small" @click="handleDelete(selectedIds)">批量删除</el-button>
        </el-col>
        <el-col :span="16">
          <el-pagination class="pagination-container" background layout="total, sizes, prev, pager, next"
            :current-page="pagination.currentPage" :page-size="pagination.pageSize" :page-sizes="pagination.sizes"
            :total="pagination.total" @size-change="handleSizeChange" @current-change="handlePageChange" />
        </el-col>
      </el-row>

      <el-dialog :title="dialog.title" :visible.sync="dialog.visible" :width="dialogWidth" :modal="dialogModal"
        :show-header="false" :close-on-click-modal="false" class="catch-form" append-to-body @opened="dialogOpened"
        @close="handleHiddenDialog">
        <form-create v-model="formCreate.fApi" :rule="formCreate.rule" :option="form.options"
          :value.sync="formCreate.value" />
      </el-dialog>
    </div>

    <form-create v-show="false" v-model="formCreate.fApi" :rule="[]" />
    <!--- 导入  -->
    <import-excel ref="import" @ok="refreshPage" />
  </div>
</template>

<script>
  import {
    isBoolean,
    isArray
  } from './type'
  import operate from './mixin/operete'

  // components
  import ElementsMapping from './components/ElementsMapping'
  import ComponentsMapping from './components/ComponentsMapping'
  import search from './components/Search'
  import importExcel from './components/Import'
  // mixins
  import create from './mixin/create'
  import update from './mixin/update'
  import del from './mixin/del'
  import view from './mixin/view'
  import to from './mixin/to'
  import _export from './mixin/export'
  import excel from './mixin/excel'
  import props from './mixin/props'
  import tableData from './mixin/tableData'

  export default {
    name: 'Table',
    components: {
      ElementsMapping,
      ComponentsMapping,
      search,
      importExcel
    },
    mixins: [operate, create, update, del, view, to, _export, excel, props, tableData],
    computed: {
      // 获取可用 refs 为止
      getParent() {
        let parent = this.$parent

        while (!Object.keys(parent.$refs).length) {
          parent = parent.$parent
        }
        return parent
      },
      // 搜索参数
      queryParams() {
        return this.$refs.search.queryParams
      },
      getTableEvents() {
        const events = this.tableEvents
        for (const key in events) {
          events[key] = this[events[key]]
        }
        return events
      },
      getForm() {
        return this.formCreate.fApi
      },

      // headers
      getHeaders() {

        return this.headers.filter(header => header.show)
      }
    },
    methods: {
      getAttrsValue(item) {
        const {
          attrs
        } = {
          attrs: item
        }
        return {
          ...attrs
        }
        // delete result.prop
        // return result
      },
      dialogOpened() {
        this.getForm.clearValidateState()
        // 表单渲染后的操作
        this.dialogOpenedFirstDo()

        this.getForm.refresh()
        // 创建时候填充数据
        if (this.form.isCreatedFillData) {
          this.getForm.setValue(this.form.data)
        }
        // 创建时
        if (this.form.data === null) {
          this.getForm.resetFields()
        } else {
          // 更新时
          this.getForm.setValue(this.form.data)
        }
        // 渲染完成之后钩子
        if (this.getParent.renderAfter !== undefined) {
          this.getParent.renderAfter(this.form.data)
        }
      },
      dialogOpenedFirstDo() {
        // 创建前操作
        if (this.getParent.beforeCreate !== undefined) {
          this.getParent.beforeCreate()
        }

        // 更新前数据操作
        if (this.form.data && this.getParent.beforeUpdate !== undefined) {
          this.getParent.beforeUpdate(this.form.data)
        }
      },
      getValue(scope, configItem) {
        const prop = configItem.prop
        const renderName = this.getMatchRenderFunction(configItem)
        const renderObj = this.renderTypeList[renderName]
        if (renderObj !== undefined) {
          return configItem[renderName]
          /** return renderObj.target
            ? this.getRenderValue(scope, configItem, { name: renderName, type: 'bind' })
            : this.getRenderValue(scope, configItem)*/
        }
        return scope.row[prop]
      },
      getRenderValue(scope, item, fn = {
        name: 'render',
        type: 'call'
      }) {
        const prop = item.prop
        const propValue = prop && scope.row[prop]
        // this.$set(scope.row, '$index', scope.$index)
        const args = propValue !== undefined ? propValue : scope.row
        return item[fn.name][fn.type](this.getParent, args)
      },
      // 匹配 render 开头的函数
      getMatchRenderFunction(obj) {
        return Object.keys(obj).find((key) => {
          if (key === 'action' || key === 'component') {
            return key
          }
        })
      },
      isActionOrComponent($item) {
        return isArray($item)
      },
      stopBubbles(e) {
        const event = e || window.event
        if (event && event.stopPropagation) {
          event.stopPropagation()
        } else {
          event.cancelBubble = true
        }
      },
      handleNativeClick({
        isBubble
      }, e) {
        // 考虑到单元格内渲染了组件，并且组件自身可能含有点击事件，故添加了阻止冒泡机制
        // 若指定 isBubble 为 false，则当前单元格恢复冒泡机制
        if (
          isBoolean(isBubble) &&
          !isBubble
        ) return
        this.stopBubbles(e)
      },
      // 获取 table 对象
      getTableObject() {
        return this
      },
      refreshPage() {
        this.getParent.getTableFrom()
      },
      // 表头按钮事件触发
      actionClick(item) {
        // 如果没有路由跳转 触发事件
        if (item.route === undefined) {
          if (this[item.click] === undefined) {
            this.getParent[item.click]()
          } else {
            this[item.click]()
          }
        } else {
          // 路由跳转
          this.$router.push(item.route)
        }
      },
      handleImport() {
        this.$refs.import.handleImport()
      }
    }
  }
</script>

<style lang="scss">
  .search-container {
    margin: 5px 15px;
    background: white;
  }

  ._import_ {
    .el-dialog__body {
      padding: 5px 20px 60px 20px;
    }

    .el-divider {
      margin: 8px 0;
    }
  }

  .search-form {
    // padding-bottom: 20px;
    text-align: right;

    .filter-item {
      display: inline-block;
      vertical-align: middle;
      margin-top: 3px;
    }

    .form-search-input {
      width: 200px;
      margin-right: 5px;
    }

    .reset,
    .search,
    .multi-delete {
      padding-left: 10px;
      padding-right: 10px;
    }
  }

  .table-list-container {
    .table-pagination {
      padding-top: 20px;
    }

    .header {
      display: flex;
      padding-bottom: 20px;

      .header-actions {
        flex: 1;
        overflow-x: auto;

        .overflow-box {
          display: flex;
          flex-direction: row-reverse;
          overflow-x: auto;
          white-space: nowrap;

          .el-button:nth-child(1) {
            margin-left: 10px;
          }
        }
      }
    }

    .el-table {
      th {
        font-size: 14px;
      }

      td {
        font-size: 14px;
      }
    }
  }
</style>
